package com.maychat.service.impl;

import com.github.pagehelper.PageHelper;
import com.maychat.config.AppConfig;
import com.maychat.config.Consts;
import com.maychat.enums.UpdateFileType;
import com.maychat.enums.UpdateStatus;
import com.maychat.exception.BusinessException;
import com.maychat.mapper.AppUpdateMapper;
import com.maychat.pojo.AppUpdate;
import com.maychat.pojo.RowsWithTotal;
import com.maychat.service.AppUpdateService;
import com.maychat.utils.StringTools;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class AppUpdateServiceImpl implements AppUpdateService {

    @Autowired
    private AppUpdateMapper appUpdateMapper;
    @Autowired
    private AppConfig appConfig;

    @Override
    public RowsWithTotal<AppUpdate> selectCondByPage(AppUpdate appUpdate, Integer page, Integer pageSize) {
        PageHelper.startPage(page, pageSize);
        List<AppUpdate> list = appUpdateMapper.selectCond(appUpdate);
        return RowsWithTotal.of(list);
    }

    @Override
    public void saveUpdate(AppUpdate appUpdate, MultipartFile file) throws BusinessException, IOException {
        UpdateFileType fileType = UpdateFileType.getByOrdinal(appUpdate.getFileType());
        Integer id = appUpdate.getId();
        if (fileType == null) throw new BusinessException();
        RowsWithTotal<AppUpdate> rows = this.selectCondByPage(new AppUpdate(), 1, 1);
        if (id == null && rows.getTotal() > 0) {
            String latestVer = rows.getRows().get(0).getVersion();
            String curVer = appUpdate.getVersion();
            int compared = StringTools.compareVersions(latestVer, curVer);
            if (compared >= 0)
                throw new BusinessException("新版本号应当大于历史版本");
        }
        if (id == null) { // 新增
            appUpdate.setCreateTime(LocalDateTime.now());
            appUpdate.setStatus(UpdateStatus.NOT_RELEASE.ordinal());
            appUpdateMapper.insert(appUpdate);
        } else { // 更新
            AppUpdate dbInfo = appUpdateMapper.selectById(id);
            if (dbInfo == null) throw new BusinessException();
            if (dbInfo.getStatus() != UpdateStatus.NOT_RELEASE.ordinal())
                throw new BusinessException("不允许修改已经发布的版本");
            appUpdate.setStatus(null);
            appUpdate.setCreateTime(null);
            appUpdate.setVersion(null);
            appUpdate.setGrayscaleUid(null);
            appUpdateMapper.updateById(appUpdate);
        }
        if (file != null) {
            String basePath = appConfig.getProjectFolder() + Consts.FOLDER_FILE_VERSIONS;
            File folder = new File(basePath);
            if (!folder.exists()) folder.mkdirs();
            file.transferTo(new File(basePath + "/" + appUpdate.getVersion()));
        }
    }

    @Override
    public void delById(Integer id) throws BusinessException {
        AppUpdate dbInfo = appUpdateMapper.selectById(id);
        if (dbInfo == null) throw new BusinessException();
        if (dbInfo.getStatus() != UpdateStatus.NOT_RELEASE.ordinal())
            throw new BusinessException("不允许删除已经发布的版本");
        appUpdateMapper.delById(id);
    }

    @Override
    public void releaseUpdate(Integer id, Integer status, String grayscaleId) throws BusinessException {
        UpdateStatus newStatus = UpdateStatus.getByOrdinal(status);
        if (newStatus == null) throw new BusinessException();
        if (newStatus.equals(UpdateStatus.GRAYSCALE)
                && StringUtils.isBlank(grayscaleId))
            throw new BusinessException("应当提供至少一个灰度UID");
        if (!newStatus.equals(UpdateStatus.GRAYSCALE))
            grayscaleId = "";
        AppUpdate appUpdate = new AppUpdate();
        appUpdate.setId(id);
        appUpdate.setStatus(newStatus.ordinal());
        appUpdate.setGrayscaleUid(grayscaleId);
        appUpdateMapper.updateById(appUpdate);
    }

    @Override
    public Map<String, Object> getLatest(String version, String uid) throws Exception {
        AppUpdate latest = appUpdateMapper.selectLatest(uid);
        if (latest == null || StringTools.compareVersions(latest.getVersion(), version) <= 0) return null;
        Map<String, Object> map = new HashMap<>();
        latest.setGrayscaleUid(null);
        map.put("updateInfo", latest);
        Long size = null;
        if (latest.getFileType() == UpdateFileType.FILE.ordinal()) {
            String path = appConfig.getProjectFolder() + Consts.FOLDER_FILE_VERSIONS + "/" + latest.getVersion();
            File file = new File(path);
            if (!file.exists()) throw new Exception();
            size = file.length();
        }
        map.put("fileName", Consts.APP_NAME + latest.getVersion());
        map.put("size", size);
        return map;
    }
}
